package com.mg.flightplan.control;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.DropboxAPI.DropboxFileInfo;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.session.TokenPair;
import com.mg.flightplan.R;
import com.mg.flightplan.domain.FlightPlan;
import com.mg.flightplan.domain.FlightPlanNvgt;
import com.mg.flightplan.domain.FlightPlanStd;
import com.mg.flightplan.domain.ICAOWaypoint;
import com.mg.flightplan.utils.DistanceConverter;
import com.mg.flightplan.utils.RouteConverter;
import com.mg.flightplan.utils.TimeConverter;

public class FplanActivity extends AbstractFPlanActivity {

	String tag="FPMAIN";
	String pathToFile =  null;
	FlightPlan flightPlan = null;

    TimerTask timerTask;
    final Handler handler = new Handler();
    Timer t = new Timer();
    private boolean flightHasStarted = false;

	RouteConverter rc = new RouteConverter();
	DistanceConverter dc = new DistanceConverter();
	TimeConverter tc = new TimeConverter();

	private int secondsPast=0;
	private int eta=0;
	TextView textEffTime=null;
	TextView arrivalIn=null;
	
	int estiSpeed=120;

	// Drop box stuff
	DropboxAPI<AndroidAuthSession> mDBApi;
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fplan);
        Log.d(tag, "Starting...");
		textEffTime=(TextView)findViewById(R.id.textEffTime);
		arrivalIn=((TextView)findViewById(R.id.arrivalIn));
		
		// Preventing application from sleeping
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		
		// Getting data from last screen
		Intent intent = getIntent();

		// We first get the cruise speed
		String cruiseSpeedGivenByUser = intent.getStringExtra(MainActivity.CRUISE_SPEED);
		if (cruiseSpeedGivenByUser!=null){
			try {
				estiSpeed = Integer.parseInt(cruiseSpeedGivenByUser);
			} catch (NumberFormatException e) {
				Log.w(tag, "Couldn't get user's cruising speed, so using the default one : "+estiSpeed);
			}
		}
		
		// We display the buttons accordingly
		setDisplayedCtrlsBeforeFlight();
		
		// Then we see if user gets FP from DB or Download
		boolean useDB =  intent.getBooleanExtra(MainActivity.USE_DB,false);

        try {

            if (!checkStorageReady()){
            	showTextBox(getString(R.string.errNoSD),null);
				throw new Exception(getString(R.string.errNoSD));
            }


    		Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdirs();
    		

			// We create a new AuthSession so that we can use the Dropbox
			// API.
			AndroidAuthSession session = buildSession();
			mDBApi = new DropboxAPI<AndroidAuthSession>(session);
            /*
             * Do we get the input flight plan from DP or the download folder ?
             */
            if (useDB){
            	// From the DB folder
            	pathToFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/fp_dp.PLN";
            	

				Log.v(tag, "mDBApi object: " + mDBApi);

				// Going through authentification process
				if (!mDBApi.getSession().authenticationSuccessful()){
			
	            	Log.v(tag, "We're not yet linked, so calling the authentication");
					mDBApi.getSession().startAuthentication(FplanActivity.this);
					
				}
				else{
					Log.v(tag, "Looks like we're authenticated already");
				}
            }
            else {
            	// From the Download folder
            	pathToFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/fp.PLN";
        		
    			File inputFile = new File(pathToFile);

            	Log.v(tag, "About to read "+inputFile.getAbsolutePath());
                if (!inputFile.exists()){
                	showTextBox(getString(R.string.errNoFile),null);
    				throw new Exception(getString(R.string.errNoFile));
                }
                
                processInputFile(inputFile);
                
            }
            
    		
    		
        }catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			Log.e(tag, e.getMessage());
		} 
    }
    

    void processInputFile(File inputFile) throws IOException, Exception{

		BufferedReader in = null;
		in = new BufferedReader(new FileReader(inputFile));

		String strLine;
		if ((strLine = in.readLine()) != null) {
			if (strLine.contains("<?xml")){
				System.out.println("Standard FSX file");
				in.close();
				flightPlan = new FlightPlanStd(inputFile);
			}
			else if (strLine.contains("[flightplan]")){
				System.out.println("Navigation file");
				in.close();
				flightPlan = new FlightPlanNvgt(inputFile);
			}
			else {
				in.close();
				throw new Exception("Non readable file");
			}
		}

		
		if (flightPlan != null){

			ICAOWaypoint wpt =  flightPlan.getLastWpt();
			if (wpt!=null)
				((TextView)findViewById(R.id.arrivalAirport)).setText(wpt.icao);
			nextWaypoint(null);	// Setting to next wpt and displaying it on the screen
			
//			showTextBox(getString(R.string.rdyToStart),new OnClickListener() {
//	            public void onClick(DialogInterface arg0, int arg1) {
//	            	launchFlight(null);
//	            }
//	        });
			
		}
    }
    
    

	@Override
	protected void onResume() {
		Log.v(tag,"In onResume() of "+FplanActivity.class.getName());
		super.onResume();
		Log.v(tag,"After super.onResume()");
		AndroidAuthSession session = mDBApi.getSession();
		
		// The next part must be inserted in the onResume() method of the
		// activity from which session.startAuthentication() was called, so
		// that Dropbox authentication completes properly.
		if (session.authenticationSuccessful()) {
			Log.v(tag,"Authentication successful");
		    try {
		        // Mandatory call to complete the auth
		        session.finishAuthentication();
				Log.v(tag,"Authentication finished");
		
		        // Store it locally in our app for later use
		        TokenPair tokens = session.getAccessTokenPair();
		        storeKeys(tokens.key, tokens.secret);
		        
		        
		        // Continue with what the application is supposed to do
		        if (!flightHasStarted) // We don't launch the process if it's already running
		        	processInputFile(readFromDB());
		        
		        
		    } catch (IllegalStateException e) {
		        Log.e(tag, "Couldn't authenticate with Dropbox:" + e.getLocalizedMessage());
		        Log.i(tag, "Error authenticating", e);
		    } catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
    

	private File readFromDB() {

		OutputStream outputStream=null;
		File f=null;
		try {
			f = new File(pathToFile);
			outputStream = new FileOutputStream(f);
			DropboxFileInfo dbInfo = mDBApi.getFile("fp_dp.PLN", null, outputStream, null);
						
		    Log.i("DbExampleLog", "The file's rev is: " + dbInfo.getMetadata().rev);

			outputStream.close();
		} catch (DropboxException e) {
			Log.e(tag,e.getMessage());
		} catch (IOException e) {
			Log.e(tag,e.getMessage());
		}
		return f;
	}

	
	
    public void launchFlight(View view){
    	flightHasStarted = true;
		timerTask = new TimerTask() {
			public void run() {
				handler.post(new Runnable() {
					
					public void run() {
						
			        	textEffTime.setText(tc.toString(secondsPast));
			        	
			        	eta -= 1; // We also remove one second from the ETA
			        	arrivalIn.setText(tc.toString(eta));
			        	
			        	Log.v(tag,"Seconds count: "+secondsPast);
			        	secondsPast ++;
					}
				});
			}
		};
		resetTimer();
		t.schedule(timerTask, 100, 1000);

		// We display the buttons accordingly
		setDisplayedCtrlsDuringFlight();
		
		// We show the arrival airport
    	((TextView)findViewById(R.id.arrivalAirport)).setText(flightPlan.getLastWpt().icao);
    	
		
    }
    
    
    void setDisplayedCtrlsBeforeFlight(){
    	// We show the launchFlight button
    	((Button)findViewById(R.id.button3)).setVisibility(View.VISIBLE);
    	((Button)findViewById(R.id.button1)).setEnabled(false);
    	((TextView)findViewById(R.id.textPreviousLbl)).setVisibility(View.GONE);
    	((TextView)findViewById(R.id.textPreviousTime)).setVisibility(View.GONE);
    }
    
    void setDisplayedCtrlsDuringFlight(){
    	// We hide the launchFlight button
    	((Button)findViewById(R.id.button3)).setVisibility(View.GONE);
    	((Button)findViewById(R.id.button1)).setEnabled(true);
    	((TextView)findViewById(R.id.textPreviousLbl)).setVisibility(View.VISIBLE);
    	((TextView)findViewById(R.id.textPreviousTime)).setVisibility(View.VISIBLE);
    }
    
    public void resetTimer(){
    	secondsPast = 0;
    	textEffTime.setText(tc.toString(secondsPast));
	}

	public void stopTimer() {

		if (timerTask != null) {
			Log.d("TIMER", "timer canceled");
			timerTask.cancel();
			t.cancel();
		}

	}
    
	@Override
	protected void onDestroy() {
		super.onDestroy();
		stopTimer();
		flightHasStarted = false;
	}


    /** Called when the user clicks the TACMMER button */
    public void nextWaypoint(View view) {
    	if (flightPlan.getCurrentWpt()!=null)
    		flightPlan.getCurrentWpt().timeTakenItGotToThatWpt = secondsPast;
    	resetTimer();
    	
    	flightPlan.moveNextWpt();
    	setWptOnInterface();
    	
    }
    
    int timeFromDistance(int dist){
    	return dist*3600/estiSpeed;
    }
    
    private void setWptOnInterface(){
    	ICAOWaypoint wpt =null;
    	
    	wpt = flightPlan.getPreviousWpt();
    	String prevTimeLbl = null;
    	if (flightPlan.getCurrWptNumber()>=2 && wpt != null){
    		prevTimeLbl=tc.toString(wpt.timeTakenItGotToThatWpt)+" / " + tc.toString(timeFromDistance((int)wpt.distFromPrevious));
    	}
    	else {
    		prevTimeLbl="N/A";
    	}
    	((TextView)findViewById(R.id.textPreviousTime)).setText(prevTimeLbl);
    	
    	
    	wpt = flightPlan.getCurrentWpt();
    	if (wpt != null){
        	((TextView)findViewById(R.id.textRoute)).setText(rc.toString(wpt.routeFromPrevious));
        	((TextView)findViewById(R.id.textDist)).setText(dc.toString(wpt.distFromPrevious));
        	((TextView)findViewById(R.id.textEstimatedTime)).setText(tc.toString(timeFromDistance((int)wpt.distFromPrevious)));
        	
        	((TextView)findViewById(R.id.wptCount)).setText(flightPlan.getCurrWptNumber()+"/"+flightPlan.getWptCount());

        	int distanceToEnd = flightPlan.getDistanceLeftToArrival();
        	eta = timeFromDistance(distanceToEnd);
        	

        	((TextView)findViewById(R.id.arrivalIn)).setText(tc.toString(eta));
    	}
    	
    	
    	
    	wpt = flightPlan.getNextWpt();
    	if (wpt != null){
        	((TextView)findViewById(R.id.textNextRoute)).setText(rc.toString(wpt.routeFromPrevious));
        	((TextView)findViewById(R.id.textNextEstimatedTime)).setText(tc.toString(timeFromDistance((int)wpt.distFromPrevious)));
    	}
    	else {
        	((TextView)findViewById(R.id.textNextRoute)).setText("");
        	((TextView)findViewById(R.id.textNextEstimatedTime)).setText("");
    	}
    }
    
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_fplan, menu);
        return true;
    }
}
